﻿using System;
using System.Collections.Generic;
using System.Text;
using Assist;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using YArchitech.Revit;

namespace YArchitech.MEP.Electric.CableLay
{
	public class ElectricalDimUtil
	{
		public static Group CreateCableTrayDim(Document doc, XYZ ptS, XYZ ptDim, LeadStyle leadStyle, LeadSymbol leadSymbol, List<string> lstData)
		{
			View activeView = doc.ActiveView;
            Autodesk.Revit.ApplicationServices.Application application = doc.Application;
			XYZ xyz = new XYZ(ptDim.X, ptDim.Y, ptS.Z);
			Plane plane = RevitVersionFuncs.CreatePlanByNormalAndOrigin(XYZ.BasisZ, ptS);
			SketchPlane.Create(doc, plane);
			ElementSet elementSet = new ElementSet();
			if (leadStyle != LeadStyle.None)
			{
				new XYZ(ptDim.X, ptDim.Y, ptS.Z);
				if (leadStyle == LeadStyle.Orthogonal)
				{
					xyz = ElectricalDimUtil.GetOrthogonalXYZ(ptS, xyz);
				}
				DetailLine detailLine = YJKRevitTools.DrawDetailLine(doc, ptS, xyz);
				elementSet.Insert(detailLine);
				if (leadSymbol != LeadSymbol.Arrow)
				{
					if (leadSymbol == LeadSymbol.Dot)
					{
						double radius = AssistFunc.mmToFeet(100.0);
						Arc arc = doc.CreatYJKArc(ptS, radius, 0.0, Math.PI, XYZ.BasisX, XYZ.BasisY);
						Arc arc2 = doc.CreatYJKArc(ptS, radius, Math.PI, Math.PI*2, XYZ.BasisX, XYZ.BasisY);
						DetailCurve detailCurve = YJKRevitTools.DrawRangLine(doc, ptS, radius);
						elementSet.Insert(detailCurve);
						ElementId hatch = ElectricalDimUtil.GetHatch(doc);
						List<CurveLoop> list = new List<CurveLoop>();
						CurveLoop curveLoop = new CurveLoop();
						curveLoop.Append(arc);
						curveLoop.Append(arc2);
						list.Add(curveLoop);
						FilledRegion filledRegion = FilledRegion.Create(doc, hatch, activeView.Id, list);
						elementSet.Insert(filledRegion);
					}
				}
				else
				{
					XYZ xyz2 = (xyz - ptS).Normalize();
					Transform transform = Transform.CreateRotationAtPoint(XYZ.BasisZ, AssistFunc.AngleToRadian(15.0), XYZ.Zero);
					xyz2 = ElectricalDimUtil.TransformPoint(xyz2, transform);
					XYZ xyz3 = ptS + xyz2;
					DetailLine detailLine2 = YJKRevitTools.DrawDetailLine(doc, ptS, xyz3);
					elementSet.Insert(detailLine2);
					Transform transform2 = Transform.CreateRotationAtPoint(XYZ.BasisZ, AssistFunc.AngleToRadian(-30.0), XYZ.Zero);
					xyz2 = ElectricalDimUtil.TransformPoint(xyz2, transform2);
					XYZ xyz4 = ptS + xyz2;
					DetailLine detailLine3 = YJKRevitTools.DrawDetailLine(doc, ptS, xyz4);
					elementSet.Insert(detailLine3);
					Line line = Line.CreateBound(ptS, xyz3);
					Line line2 = Line.CreateBound(xyz3, xyz4);
					Line line3 = Line.CreateBound(xyz4, ptS);
					List<CurveLoop> list2 = new List<CurveLoop>();
					ElementId hatch2 = ElectricalDimUtil.GetHatch(doc);
					CurveLoop curveLoop2 = new CurveLoop();
					curveLoop2.Append(line);
					curveLoop2.Append(line2);
					curveLoop2.Append(line3);
					list2.Add(curveLoop2);
					FilledRegion filledRegion2 = FilledRegion.Create(doc, hatch2, activeView.Id, list2);
					elementSet.Insert(filledRegion2);
				}
			}
			IEnumerable<Element> enumerable = new FilteredElementCollector(doc).OfClass(typeof(TextNoteType)).ToElements();
			double num = AssistFunc.mmToFeet(3.0);
			double num2 = 0.7;
			ElementId elementId = new ElementId(0);
			foreach (Element element in enumerable)
			{
				TextNoteType textNoteType = (TextNoteType)element;
				if (textNoteType.Name == "HY-微软雅黑-3.0-0.7")
				{
					num = textNoteType.get_Parameter(BuiltInParameter.TEXT_SIZE).AsDouble();
					num2 = textNoteType.get_Parameter(BuiltInParameter.TEXT_WIDTH_SCALE).AsDouble();
					elementId = textNoteType.Id;
					break;
				}
			}
			string maxStr = ElectricalDimUtil.GetMaxStr(lstData);
			byte[] bytes = Encoding.Default.GetBytes(maxStr);
			double num3 = num * num2;
			double num4 = (double)bytes.Length * num3;
			num *= 2.0;
			XYZ xyz5 = null;
			XYZ xyz6 = null;
			XYZ xyz7 = xyz;
            TextAlignFlags textAlign = (TextAlignFlags)2112;
			int num5 = ElectricalDimUtil.Quadrant(ptS, ptDim);
			if (num5 == 1)
			{
				xyz5 = XYZ.BasisY * num * (double)activeView.Scale;
				xyz6 = XYZ.BasisX * num4 * (double)activeView.Scale;
				lstData.Reverse();
			}
			else if (num5 == 2)
			{
				xyz5 = XYZ.BasisY * num * (double)activeView.Scale;
				xyz6 = -XYZ.BasisX * num4 * (double)activeView.Scale;
				lstData.Reverse();
                textAlign = (TextAlignFlags)2304;
			}
			else if (num5 == 3)
			{
				xyz5 = -XYZ.BasisY * num * (double)activeView.Scale;
				xyz6 = -XYZ.BasisX * num4 * (double)activeView.Scale;
                textAlign = (TextAlignFlags)2304;
			}
			else if (num5 == 4)
			{
				xyz5 = -XYZ.BasisY * num * (double)activeView.Scale;
				xyz6 = XYZ.BasisX * num4 * (double)activeView.Scale;
				xyz7 += XYZ.BasisX * AssistFunc.mmToFeet(60.0);
			}
			xyz7 = RevitElementExtension.GetTextNotePosition(xyz7, num5, num, num4, activeView);
			foreach (string strText in lstData)
			{
				TextNote textNode = doc.GetTextNode(activeView, xyz7, XYZ.BasisX, XYZ.BasisY, num4 * 2.0, textAlign, strText);
				textNode.ChangeTypeId(elementId);
				elementSet.Insert(textNode);
				DetailLine detailLine4 = YJKRevitTools.DrawDetailLine(doc, xyz, xyz + xyz6);
				elementSet.Insert(detailLine4);
				DetailLine detailLine5 = YJKRevitTools.DrawDetailLine(doc, xyz, xyz + xyz5);
				elementSet.Insert(detailLine5);
				foreach (ElementId elementId2 in ElementTransformUtils.CopyElement(doc, detailLine5.Id, xyz6))
				{
					elementSet.Insert(doc.GetElement(elementId2));
				}
				xyz += xyz5;
				xyz7 += xyz5;
			}
			DetailLine detailLine6 = YJKRevitTools.DrawDetailLine(doc, xyz, xyz + xyz6);
			elementSet.Insert(detailLine6);
			return doc.CreatYJKGroup(elementSet);
		}

		public static XYZ GetOrthogonalXYZ(XYZ ptDimFirst, XYZ ptDimSecond)
		{
			double num = ptDimFirst.DistanceTo(ptDimSecond);
			XYZ xyz = ptDimSecond - ptDimFirst;
			double num2 = XYZ.BasisX.AngleOnPlaneTo(xyz, XYZ.BasisZ);
			int num3 = ElectricalDimUtil.Quadrant8(num2, true);
			if (num3 == 1 || num3 == 8)
			{
				xyz = XYZ.BasisX;
			}
			else if (num3 == 2 || num3 == 3)
			{
				xyz = XYZ.BasisY;
			}
			else if (num3 == 4 || num3 == 5)
			{
				xyz = -XYZ.BasisX;
			}
			else if (num3 == 6 || num3 == 7)
			{
				xyz = -XYZ.BasisY;
			}
			ptDimSecond = ptDimFirst + xyz * (num * Math.Abs(Math.Sin(num2)));
			return ptDimSecond;
		}

		public static int Quadrant(XYZ ptBase, XYZ ptTag)
		{
			XYZ xyz = ptTag - ptBase;
			return ElectricalDimUtil.Quadrant(XYZ.BasisX.AngleOnPlaneTo(xyz, XYZ.BasisZ), true);
		}

		public static int Quadrant(double angle, bool arc)
		{
			if (!arc)
			{
				if (angle > 0.0 && angle < 90.0)
				{
					return 1;
				}
				if (angle > 90.0 && angle < 180.0)
				{
					return 2;
				}
				if (angle > 180.0 && angle < 270.0)
				{
					return 3;
				}
				return 4;
			}
			else
			{
				if (angle > 0.0 && angle < Math.PI*.5)
				{
					return 1;
				}
				if (angle > Math.PI*.5 && angle < Math.PI)
				{
					return 2;
				}
				if (angle > Math.PI && angle < 4.71238898038469)
				{
					return 3;
				}
				return 4;
			}
		}

		public static int Quadrant8(double angle, bool arc)
		{
			if (!arc)
			{
				if (angle > 0.0 && angle < 45.0)
				{
					return 1;
				}
				if (angle > 45.0 && angle < 90.0)
				{
					return 2;
				}
				if (angle > 90.0 && angle < 135.0)
				{
					return 3;
				}
				if (angle > 135.0 && angle < 180.0)
				{
					return 4;
				}
				if (angle > 180.0 && angle < 225.0)
				{
					return 5;
				}
				if (angle > 225.0 && angle < 270.0)
				{
					return 6;
				}
				if (angle > 270.0 && angle < 315.0)
				{
					return 7;
				}
				return 8;
			}
			else
			{
				if (angle > 0.0 && angle < 0.78539816339744828)
				{
					return 1;
				}
				if (angle > 0.78539816339744828 && angle < Math.PI*.5)
				{
					return 2;
				}
				if (angle > Math.PI*.5 && angle < 2.3561944901923448)
				{
					return 3;
				}
				if (angle > 2.3561944901923448 && angle < Math.PI)
				{
					return 4;
				}
				if (angle > Math.PI && angle < 3.9269908169872414)
				{
					return 5;
				}
				if (angle > 3.9269908169872414 && angle < 4.71238898038469)
				{
					return 6;
				}
				if (angle > 4.71238898038469 && angle < 5.497787143782138)
				{
					return 7;
				}
				return 8;
			}
		}

		public static XYZ TransformPoint(XYZ point, Transform transform)
		{
			double x = point.X;
			double y = point.Y;
			double z = point.Z;
			XYZ xyz = transform.get_Basis(0);
			XYZ xyz2 = transform.get_Basis(1);
			XYZ xyz3 = transform.get_Basis(2);
			XYZ origin = transform.Origin;
			double num = x * xyz.X + y * xyz2.X + z * xyz3.X + origin.X;
			double num2 = x * xyz.Y + y * xyz2.Y + z * xyz3.Y + origin.Y;
			double num3 = x * xyz.Z + y * xyz2.Z + z * xyz3.Z + origin.Z;
			return new XYZ(num, num2, num3);
		}

		public static ElementId GetHatch(Document doc)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(FilledRegionType));
			FilledRegionType filledRegionType = null;
			foreach (Element element in filteredElementCollector.ToElements())
			{
				if (element.Name == "black")
				{
					filledRegionType = (element as FilledRegionType);
					break;
				}
			}
			if (filledRegionType == null)
			{
				SubTransaction subTransaction = new SubTransaction(doc);
				subTransaction.Start();
				ElementId fillPatternId = new ElementId(19);
				filledRegionType = ((filteredElementCollector.ToElements()[0] as FilledRegionType).Duplicate("black") as FilledRegionType);
				FilteredElementCollector filteredElementCollector2 = new FilteredElementCollector(doc);
				filteredElementCollector2.OfClass(typeof(FillPatternElement));
				foreach (Element element2 in filteredElementCollector2.ToElements())
				{
					if (element2.Name == "实体填充")
					{
						fillPatternId = element2.Id;
						break;
					}
				}
				filledRegionType.FillPatternId = fillPatternId;
				subTransaction.Commit();
			}
			return filledRegionType.Id;
		}

		public static string GetMaxStr(List<string> lstItem)
		{
			string result = null;
			int num = 0;
			foreach (string text in lstItem)
			{
				byte[] bytes = Encoding.Default.GetBytes(text);
				if (num < bytes.Length)
				{
					num = bytes.Length;
					result = text;
				}
			}
			return result;
		}
	}
}
